#include "tcpmgr.h"
#include <QJsonDocument>
#include <QJsonObject>



TcpMgr::TcpMgr():_host(""),_port(0),_bRecvPending(false),_messageId(0),_messageLen(0)
{
    // 连接建立时
    QObject::connect(&_socket,&QTcpSocket::connected,[=](){
        qDebug() << "the url:"<< _host+':'+QString::number(_port) << "\t connect";
        emit SigConSuccess(true);
    });
    QObject::connect(&_socket,&QTcpSocket::readyRead,[&](){
        qDebug() << "get data";
        // 读取全部数据到_buffer中
        _buffer.append(_socket.readAll());
        QDataStream stream(&_buffer, QIODevice::ReadOnly);
        // 处理粘包问题
        forever{
            // 判断长度是否有4个字节 因为消息结构为 id+len+data
            if(!_bRecvPending){
                if(_buffer.size() < static_cast<int>(sizeof(quint16) * 2)){
                    qDebug() << "数据长度太短，无法读取id和长度" << _buffer.size();
                    return ;
                }
                // 说明头读取好了
                stream >> _messageId >> _messageLen;
                // 移除头
               _buffer =  _buffer.mid(sizeof(quint16) * 2);
                // 输出读取的数据
                qDebug() << "Message ID:" << _messageId << ", Length:" << _messageLen;
                _bRecvPending = true; //不用解析头部了
            }
            // 说明读取的长度小于data长度
            if(_buffer.size()<_messageLen){
                return ;
            }
            // 说明长度够了
            _bRecvPending = false;
            // 读取数据
            QByteArray messageBody = _buffer.mid(0, _messageLen);
            qDebug() << "receive body msg is " << messageBody ;
            // 执行读取的函数
            handleMsg(ReqId(_messageId),messageBody);
            //移除数据
            _buffer = _buffer.mid(_messageLen);

        }
    });
    QObject::connect(&_socket, static_cast<void (QTcpSocket::*)(QTcpSocket::SocketError)>(&QTcpSocket::error),
                                [&](QTcpSocket::SocketError socketError) {
        qDebug() << "Error:" << _socket.errorString() ;
                       switch (socketError) {
                           case QTcpSocket::ConnectionRefusedError:
                               qDebug() << "连接异常：拒绝连接!";
                               emit SigConSuccess(false);
                               break;
                           case QTcpSocket::RemoteHostClosedError:
                               qDebug() << "连接异常：对方关闭连接!";
                               break;
                           case QTcpSocket::HostNotFoundError:
                               qDebug() << "连接异常：url没有找到!";
                               emit SigConSuccess(false);
                               break;
                           case QTcpSocket::SocketTimeoutError:
                               qDebug() << "连接异常：连接超时!";
                               emit SigConSuccess(false);
                               break;
                           case QTcpSocket::NetworkError:
                               qDebug() << "连接异常：网络异常!";
                               break;
                           default:
                               qDebug() << "连接异常：其他错误!";
                               break;
                       }
    });

       QObject::connect(&_socket,&QTcpSocket::disconnected,[&](){
            qDebug() << "Disconnected from server.";
       });

    QObject::connect(this,&TcpMgr::SigSendData,this,&TcpMgr::SlotSendData);
    initHandler();
}

TcpMgr::~TcpMgr()
{

}

void TcpMgr::initHandler()
{
    _handlers.insert(ReqId::ID_CHAT_LOGIN_RSP,[this](const QJsonObject& jsonObj){
        if (!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_CHAT_LOGIN_RSP 无法找到error参数或eroor异常：" << err;
            emit SigLoginFaild(err);
            return;
        }
        auto uid = jsonObj["uid"].toInt();
        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto user_info = std::make_shared<UserInfo>(uid, name, nick, icon, sex);
        UserMgr::GetInstance()->SetUserInfo(user_info);
        UserMgr::GetInstance()->SetToken(jsonObj["token"].toString());
        if(jsonObj.contains("apply_list")){
            UserMgr::GetInstance()->AppendApplyList(jsonObj["apply_list"].toArray());
        }

        //添加好友列表
        if (jsonObj.contains("friend_list")) {
            UserMgr::GetInstance()->AppendFriendList(jsonObj["friend_list"].toArray());
        }

        emit SigSwitchChatDLG();

        emit SigSwitchChatDLG();
    });

    _handlers.insert(ReqId::ID_SEARCH_USER_RSP, [this](const QJsonObject& jsonObj){
        if(!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_SEARCH_USER_RSP 无法找到error参数或eroor异常：" << err;
            emit SigUserSearch(nullptr);
            return;
        }
      auto search_info = std::make_shared<SearchInfo>(jsonObj["uid"].toInt(),
              jsonObj["name"].toString(), jsonObj["nick"].toString(),
              jsonObj["desc"].toString(), jsonObj["sex"].toInt(), jsonObj["icon"].toString());
       emit SigUserSearch(search_info);

    });

    _handlers.insert(ReqId::ID_NOTIFY_ADD_FRIEND_REQ,[this](const QJsonObject& jsonObj){
        if(!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_ADD_FRIEND_REQ 无法找到error参数或eroor异常：" << err;
            emit SigUserSearch(nullptr);
            return;
        }
         int from_uid = jsonObj["applyuid"].toInt();
         QString name = jsonObj["name"].toString();
         QString desc = jsonObj["desc"].toString();
         QString icon = jsonObj["icon"].toString();
         QString nick = jsonObj["nick"].toString();
         int sex = jsonObj["sex"].toInt();

        auto apply_info = std::make_shared<AddFriendApply>(
                    from_uid, name, desc,
                      icon, nick, sex);
        emit SigFriendApply(apply_info);
    });
    _handlers.insert(ReqId::ID_AUTH_FRIEND_RSP, [this](const QJsonObject& jsonObj) {
        if(!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_AUTH_FRIEND_RSP 无法找到error参数或eroor异常：" << err;
            return;
        }

        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto uid = jsonObj["uid"].toInt();
        auto rsp = std::make_shared<AuthRsp>(uid, name, nick, icon, sex);
        emit SigAuthRsp(rsp);

        qDebug() << "Auth Friend Success " ;
      });
    _handlers.insert(ReqId::ID_NOTIFY_AUTH_FRIEND_REQ, [this](const QJsonObject& jsonObj) {
        if(!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_NOTIFY_AUTH_FRIEND_REQ 无法找到error参数或eroor异常：" << err;
            return;
        }

        int from_uid = jsonObj["fromuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString nick = jsonObj["nick"].toString();
        QString icon = jsonObj["icon"].toString();
        int sex = jsonObj["sex"].toInt();

        auto auth_info = std::make_shared<AuthInfo>(from_uid,name,
                                                    nick, icon, sex);

        emit SigAddAuthFriend(auth_info);
        });
    _handlers.insert(ReqId::ID_TEXT_CHAT_MSG_RSP, [this](const QJsonObject& jsonObj) {
        if(!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_TEXT_CHAT_MSG_RSP 无法找到error参数或eroor异常：" << err;
            return;
        }

        qDebug() << "Receive Text Chat Rsp Success " ;
        //ui设置送达等标记 todo...
      });
    _handlers.insert(ReqId::ID_NOTIFY_TEXT_CHAT_MSG_REQ, [this](const QJsonObject& jsonObj) {
        if(!jsonObj.contains("error") || jsonObj["error"].toInt() != ErrorCodes::SUCCESS){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TcpMgr::initHandler ID_NOTIFY_TEXT_CHAT_MSG_REQ 无法找到error参数或eroor异常：" << err;
            return;
        }

        qDebug() << "Receive Text Chat Notify Success " ;
        auto msg_ptr = std::make_shared<TextChatMsg>(jsonObj["fromuid"].toInt(),
                jsonObj["touid"].toInt(),jsonObj["text_array"].toArray());
        emit SigTextChatMsg(msg_ptr);
      });
}

void TcpMgr::handleMsg(ReqId id, QByteArray data)
{
    auto find_iter =  _handlers.find(id);
    if(find_iter == _handlers.end()){
         qDebug()<< "not found id ["<< id << "] to handle";
         return ;
    }
    // 把data转json
    // 将QByteArray转换为QJsonDocument
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
    // 检查转换是否成功
    if (jsonDoc.isNull()) {
        qDebug() << "Failed to create QJsonDocument.";
        return;
    }
    QJsonObject jsonObj = jsonDoc.object();
    // 说明成功 解析
    find_iter.value()(jsonObj);
    return ;
}

void TcpMgr::SlotTcpConnect(ServerInfo si)
{
    qDebug()<< "receive tcp connect signal:\t"<<si.Host+':'+si.Port;
    // 尝试连接到服务器
    qDebug() << "Connecting to server...";
    _host = si.Host;
    _port = static_cast<uint16_t>(si.Port.toUInt());
    _socket.connectToHost(si.Host, _port);

}

// 通过槽函数可以实现线程保护
void TcpMgr::SlotSendData(ReqId reqId, QString data)
{
    uint16_t id =reqId;
    // 数据修改为utf-8
    QByteArray dataBytes = data.toUtf8();
    // 转大端序
    quint16 len = static_cast<quint16>(dataBytes.size());
    QByteArray block;
    QDataStream out(&block,QIODevice::WriteOnly);//只读
    out.setByteOrder(QDataStream::BigEndian);
    // 数据加入到block中
    out << id << len;// 把id和len通过QDataStream，从out加入到block中
    block.append(data);// 再添加数据
    // 写数据
     _socket.write(block);
}
